/*******************************************************************
 *
 * Copyright (C), 2021-2022, Letstrong, All rights reserved.
 *
 * Author      : 
 * Create Time : 2020-12-14
 * Version     : v0.1
 * Description : 
 *******************************************************************/

/*----------------------------Head file----------------------------*/
#include "rwip_config.h" // RW SW configuration

#include "arch.h"      // architectural platform definitions
#include <stdlib.h>    // standard lib functions
#include <stddef.h>    // standard definitions
#include <stdint.h>    // standard integer definition
#include <stdbool.h>   // boolean definition
#include "boot.h"      // boot definition
#include "rwip.h"      // RW SW initialization
#include "syscntl.h"   // System control initialization
#include "emi.h"       // EMI initialization
#include "intc.h"      // Interrupt initialization
#include "timer.h"     // TIMER initialization
#include "icu.h"
#include "uart.h"      	// UART initialization
#include "flash.h"     // Flash initialization
//#include "led.h"       // Led initialization
#if (BLE_EMB_PRESENT || BT_EMB_PRESENT)
#include "rf.h"        // RF initialization
#endif // BLE_EMB_PRESENT || BT_EMB_PRESENT

#if (BLE_APP_PRESENT)
#include "app.h"       // application functions
#endif // BLE_APP_PRESENT

#if (NVDS_SUPPORT)
#include "nvds.h"                    // NVDS Definitions
#endif
#include "reg_assert_mgr.h"
#include "BK3432_reg.h"
#include "RomCallFlash.h"
#include "app_task.h"
#include "ir.h"
#include "ota.h"
#include "wdt.h"
#include "app_misc.h"
#include "sys_task.h"
#include "user_config.h"
#include "app_store_set_info.h"
#include "log.h"

/*----------------------------macro file---------------------------*/

/*----------------------------type define--------------------------*/
struct rwip_eif_api uart_api;

/*----------------------------var define---------------------------*/
extern struct rom_env_tag rom_env;

/*-------------------------func declaration------------------------*/
void rwip_eif_api_init(void);
static void Stack_Integrity_Check(void);

/*-----------------------------------------------------------------*/


void assert_err(const char *condition, const char * file, int line)
{
	LOG_ERROR("%s,condition %s,file %s,line = %d\r\n",__func__,condition,file,line);
}

void assert_param(int param0, int param1, const char * file, int line)
{
	LOG_ERROR("%s,param0 = %d,param1 = %d,file = %s,line = %d\r\n",__func__,param0,param1,file,line);
}

void assert_warn(int param0, int param1, const char * file, int line)
{
	LOG_ERROR("%s,param0 = %d,param1 = %d,file = %s,line = %d\r\n",__func__,param0,param1,file,line);
}

void dump_data(uint8_t* data, uint16_t length)
{
	LOG_ERROR("%s,data = %d,length = %d,file = %s,line = %d\r\n",__func__,data,length);
}


void platform_reset(uint32_t error)
{
	//LOG_DEBUG("error = %x\r\n", error);

	// Disable interrupts
	GLOBAL_INT_STOP();

#if UART_PRINTF_EN
	// Wait UART transfer finished
	uart_finish_transfers();
#endif

	if(error == RESET_AND_LOAD_FW || error == RESET_TO_ROM)
	{
		// Not yet supported
	}
	else
	{
		wdt_enable(10);
		while(1);
	}
}

void bdaddr_env_init(void)
{
	struct bd_addr co_bdaddr;
	
#if(DEV_MAC_BURN_ENABLE)
	if(DEV_MAC_LEN != app_set_info_burn_mac_get(co_bdaddr.addr))
	{
#endif
		flash_read(FLASH_SPACE_TYPE_MAIN, BLE_MAC_SAVED_ADDR/4, 6, &co_bdaddr.addr[0]);
		if(co_bdaddr.addr[0]!=0xff || co_bdaddr.addr[1]!=0xff || \
				co_bdaddr.addr[2]!=0xff || co_bdaddr.addr[3]!=0xff || \
				co_bdaddr.addr[4]!=0xff || co_bdaddr.addr[5]!=0xff )
		{
			memcpy(&co_default_bdaddr, &co_bdaddr, 6);
		}
#if(DEV_MAC_BURN_ENABLE)
	}
	else {
		memcpy(&co_default_bdaddr, &co_bdaddr, 6);
		g_app_data.sys.state.dev_mac_valid = true;
	}
#endif

	LOG_DEBUG("BD, %x:%x:%x:%x:%x:%x\r\n", co_bdaddr.addr[0], co_bdaddr.addr[1], co_bdaddr.addr[2], \
					co_bdaddr.addr[3], co_bdaddr.addr[4], co_bdaddr.addr[5]);
}


void rw_main(void)
{
	/*
	 ***************************************************************************
	 * Platform initialization
	 ***************************************************************************
	 */
#if SYSTEM_SLEEP
	uint8_t sleep_type = 0;
#endif
	icu_init();

	// Initialize random process
	srand(1);

	//get System sleep flag
	system_sleep_init();

	// Initialize the exchange memory interface
	emi_init();

	rwip_eif_api_init();

	// Initialize the Interrupt Controller
	intc_init();

	// Initialize UART component
#if UART_PRINTF_EN
	dgb_uart_init(DBG_UART_BAUDRATE);
#endif
	
	// Initialize the internal flash
	flash_init();

	rom_env_init(&rom_env);

	/****************************************************************************
	  * RW SW stack initialization
	****************************************************************************/
	//Enable ble clock
	REG_AHB0_ICU_BLECLKCON = 0;

	// Initialize RW SW stack
	rwip_init(0);

	app_global_data_init();
	bdaddr_env_init();

	REG_AHB0_ICU_INT_ENABLE |= INT_STATUS_BLE_bit; //BLE INT
	REG_AHB0_ICU_IRQ_ENABLE = (INT_IRQ_BIT | FIQ_IRQ_BIT);

	//Rope system init
	sys_task_init();
	app_peripheral_init();

	// finally start interrupt handling
	GLOBAL_INT_START();

	LOG_DEBUG("start\n");
	while(1)
	{
		//schedule all pending events
		rwip_schedule();
		
		//Scale task execute, put this after ble task.
		sys_task_sched_execute();
		
		// Checks for sleep have to be done with interrupt disabled
		GLOBAL_INT_DISABLE();

		if(wdt_disable_flag == 1)
		{
			wdt_disable();
		}

#if SYSTEM_SLEEP
		// Check if the processor clock can be gated
		sleep_type = rwip_sleep();
		if((sleep_type & RW_MCU_DEEP_SLEEP) == RW_MCU_DEEP_SLEEP)
		{
			// 1:idel  0:reduce voltage
			if(icu_get_sleep_mode())
			{
				cpu_idle_sleep();
			}
			else
			{
				cpu_reduce_voltage_sleep();
			}
		}
		else if((sleep_type & RW_MCU_IDLE_SLEEP) == RW_MCU_IDLE_SLEEP)
		{
			cpu_idle_sleep();
		}
#endif
		Stack_Integrity_Check();
		GLOBAL_INT_RESTORE();
	}
}

void rwip_eif_api_init(void)
{
	uart_api.read = &uart_read;
	uart_api.write = &uart_write;
	uart_api.flow_on = &uart_flow_on;
	uart_api.flow_off = &uart_flow_off;
}

const struct rwip_eif_api* rwip_eif_get(uint8_t type)
{
	const struct rwip_eif_api* ret = NULL;
	switch(type)
	{
		case RWIP_EIF_AHI: {
			ret = &uart_api;
		} break;
#if (BLE_EMB_PRESENT) || (BT_EMB_PRESENT)
		case RWIP_EIF_HCIC: {
			ret = &uart_api;
		} break;
#elif !(BLE_EMB_PRESENT) || !(BT_EMB_PRESENT)
		case RWIP_EIF_HCIH: {
			ret = &uart_api;
		} break;
#endif
		default: {
			ASSERT_INFO(0, type, 0);
		} break;
	}
	return ret;
}

static void Stack_Integrity_Check(void)
{
	if ((REG_PL_RD(STACK_BASE_UNUSED)!= BOOT_PATTERN_UNUSED))
	{
		while(1)
		{
			LOG_ERROR("STACK_BASE_UNUSED fail!\r\n");
		}
	}

	if ((REG_PL_RD(STACK_BASE_SVC)!= BOOT_PATTERN_SVC))
	{
		while(1)
		{
			LOG_ERROR("STACK_BASE_SVC fail!\r\n");
		}
	}

	if ((REG_PL_RD(STACK_BASE_FIQ)!= BOOT_PATTERN_FIQ))
	{
		while(1)
		{
			LOG_ERROR("STACK_BASE_FIQ fail!\r\n");
		}
	}

	if ((REG_PL_RD(STACK_BASE_IRQ)!= BOOT_PATTERN_IRQ))
	{
		while(1)
		{
			LOG_ERROR("STACK_BASE_IRQ fail!\r\n");
		}
	}
}


void rom_env_init(struct rom_env_tag *api)
{
	memset(&rom_env,0,sizeof(struct rom_env_tag));
	rom_env.prf_get_id_from_task = prf_get_id_from_task;
	rom_env.prf_get_task_from_id = prf_get_task_from_id;
	rom_env.prf_init = prf_init;
	rom_env.prf_create = prf_create;
	rom_env.prf_cleanup = prf_cleanup;
	rom_env.prf_add_profile = prf_add_profile;
	rom_env.rwble_hl_reset = rwble_hl_reset;
	rom_env.rwip_reset = rwip_reset;
#if SYSTEM_SLEEP
	rom_env.rwip_prevent_sleep_set = rwip_prevent_sleep_set;
	rom_env.rwip_prevent_sleep_clear = rwip_prevent_sleep_clear;
	rom_env.rwip_sleep_lpcycles_2_us = rwip_sleep_lpcycles_2_us;
	rom_env.rwip_us_2_lpcycles = rwip_us_2_lpcycles;
	rom_env.rwip_wakeup_delay_set = rwip_wakeup_delay_set;
#endif
	rom_env.platform_reset = platform_reset;
	rom_env.assert_err = assert_err;
	rom_env.assert_param = assert_param;
	rom_env.Read_Uart_Buf = Read_Uart_Buf;
	rom_env.uart_clear_rxfifo = uart_clear_rxfifo;
}

